package demoMod.invincibleOne.actions;

import basemod.BaseMod;
import basemod.ReflectionHacks;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.screens.CardRewardScreen;
import com.megacrit.cardcrawl.vfx.cardManip.ShowCardAndAddToDrawPileEffect;
import demoMod.invincibleOne.cards.invincible.SporeSpray;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class ChooseOneAddToDrawPileAction extends AbstractGameAction {
    private boolean retrieveCard = false;
    private final Predicate<AbstractCard> condition;

    public ChooseOneAddToDrawPileAction(Predicate<AbstractCard> condition) {
        this.actionType = ActionType.CARD_MANIPULATION;
        this.duration = Settings.ACTION_DUR_FAST;
        this.condition = condition;
    }

    public void update() {
        if (AbstractDungeon.getMonsters().areMonstersBasicallyDead()) {
            this.isDone = true;
        } else if (this.duration == Settings.ACTION_DUR_FAST) {
            AbstractDungeon.cardRewardScreen.customCombatOpen(this.generateCardChoices(), CardRewardScreen.TEXT[1], true);
            this.tickDuration();
        } else {
            if (!this.retrieveCard) {
                if (AbstractDungeon.cardRewardScreen.discoveryCard != null) {
                    AbstractCard codexCard = AbstractDungeon.cardRewardScreen.discoveryCard.makeStatEquivalentCopy();
                    codexCard.current_x = -1000.0F * Settings.xScale;
                    AbstractDungeon.effectList.add(new ShowCardAndAddToDrawPileEffect(codexCard, (float)Settings.WIDTH / 2.0F, (float)Settings.HEIGHT / 2.0F, true));
                    AbstractDungeon.cardRewardScreen.discoveryCard = null;
                }

                this.retrieveCard = true;
            }

            this.tickDuration();
        }
    }

    private ArrayList<AbstractCard> generateCardChoices() {
        List<AbstractCard> pool = BaseMod.getCustomCardsToAdd().stream().filter(condition).collect(Collectors.toList());
        Collections.shuffle(pool, new Random(AbstractDungeon.cardRandomRng.randomLong()));
        ArrayList<AbstractCard> derp = new ArrayList<>();

        while(derp.size() != 3) {
            boolean dupe = false;
            AbstractCard.CardRarity rarity = ReflectionHacks.privateStaticMethod(AbstractDungeon.class, "getCardRarityFallback", int.class).invoke(new Object[]{AbstractDungeon.cardRandomRng.random(100)});
            AbstractCard tmp = pool.stream().filter(c -> c.rarity == rarity && !c.tags.contains(AbstractCard.CardTags.HEALING)).findFirst().orElseGet(SporeSpray::new);
            pool.remove(tmp);

            for (AbstractCard c : derp) {
                if (c.cardID.equals(tmp.cardID)) {
                    dupe = true;
                    break;
                }
            }

            if (!dupe) {
                AbstractCard c = tmp.makeCopy();
                c.upgrade();
                derp.add(c);
            }
            Collections.shuffle(pool, new Random(AbstractDungeon.cardRandomRng.randomLong()));
        }

        return derp;
    }
}
